<template>
  <div class="network-log" v-loading="loading">
    <div class="page-header">
      <h1 class="page-title">网络日志接收监控</h1>
      <div class="header-actions">
        <el-button type="primary" @click="refreshData" :loading="refreshing">
          <el-icon><Refresh /></el-icon> 刷新数据
        </el-button>
        <el-button type="success" @click="handleExport" :disabled="safeRecentLogs.length === 0">
          <el-icon><Download /></el-icon> 导出日志
        </el-button>
      </div>
    </div>
    
    <!-- 统计卡片组 -->
    <el-row :gutter="16" class="stats-row">
      <el-col :xs="12" :sm="6">
        <el-card shadow="hover" class="stat-card">
          <el-statistic title="总接收数" :value="totalReceived">
            <template #prefix>
              <el-icon color="#409eff" :size="20"><Document /></el-icon>
            </template>
          </el-statistic>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="6">
        <el-card shadow="hover" class="stat-card success">
          <el-statistic title="成功处理" :value="monitorData.successCount || 0">
            <template #prefix>
              <el-icon color="#67c23a" :size="20"><CircleCheck /></el-icon>
            </template>
          </el-statistic>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="6">
        <el-card shadow="hover" class="stat-card danger">
          <el-statistic title="处理失败" :value="monitorData.failCount || 0">
            <template #prefix>
              <el-icon color="#f56c6c" :size="20"><CircleClose /></el-icon>
            </template>
          </el-statistic>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="6">
        <el-card shadow="hover" class="stat-card">
          <el-statistic title="成功率" :value="successRate" suffix="%">
            <template #prefix>
              <el-icon :color="getSuccessRateColor(successRate)" :size="20"><TrendCharts /></el-icon>
            </template>
          </el-statistic>
        </el-card>
      </el-col>
    </el-row>
    
    <!-- 服务状态和日志级别分布 -->
    <el-row :gutter="20" style="margin-top: 20px">
      <el-col :xs="24" :md="12">
        <el-card class="service-card">
          <template #header>
            <div class="card-header">
              <el-icon :size="24" color="#409eff"><Connection /></el-icon>
              <span style="margin-left: 10px; font-weight: bold">TCP服务状态</span>
              <el-tag :type="serverRunning ? 'success' : 'danger'" size="small" style="margin-left: auto">
                {{ serverRunning ? '运行中' : '已停止' }}
              </el-tag>
            </div>
          </template>
          <el-descriptions :column="1" border>
            <el-descriptions-item label="监听端口">
              <el-tag type="info">9999</el-tag>
            </el-descriptions-item>
            <el-descriptions-item label="成功率">
              <el-progress 
                :percentage="successRate" 
                :color="getProgressColor(successRate)"
                :stroke-width="14"
              />
            </el-descriptions-item>
            <el-descriptions-item label="最后接收时间">
              <span style="color: #909399">{{ monitorData.lastCollectTime || '暂无数据' }}</span>
            </el-descriptions-item>
            <el-descriptions-item label="运行状态">
              <el-tag v-if="monitorData.errorMsg" type="danger" size="small">
                错误: {{ monitorData.errorMsg }}
              </el-tag>
              <el-tag v-else type="success" size="small">✅ 运行正常</el-tag>
            </el-descriptions-item>
          </el-descriptions>
          
          <el-divider />
          
          <el-alert
            title="服务说明"
            type="info"
            :closable="false"
            show-icon
          >
            <p>📡 Netty TCP服务监听端口：9999</p>
            <p>📊 实时统计网络日志接收情况</p>
            <p>🔄 数据每5秒自动刷新</p>
          </el-alert>
        </el-card>
      </el-col>
      
      <el-col :xs="24" :md="12">
        <el-card class="stats-card">
          <template #header>
            <div class="card-header">
              <el-icon :size="24" color="#e6a23c"><PieChart /></el-icon>
              <span style="margin-left: 10px; font-weight: bold">日志级别分布</span>
            </div>
          </template>
          <div class="level-stats">
            <div class="level-item" v-for="item in levelStats" :key="item.level">
              <div class="level-header">
                <el-tag :type="getLevelType(item.level)" size="small">{{ item.level }}</el-tag>
                <span class="level-count">{{ item.count }} 条</span>
              </div>
              <el-progress 
                :percentage="item.percentage" 
                :color="getLevelColor(item.level)"
                :stroke-width="10"
                :show-text="false"
              />
            </div>
            <el-empty v-if="levelStats.length === 0" description="暂无数据" :image-size="80" />
          </div>
        </el-card>
      </el-col>
    </el-row>
    
    <!-- 最近接收的日志 -->
    <el-card style="margin-top: 20px" class="log-card">
      <template #header>
        <div class="card-header">
          <div class="header-left">
            <el-icon :size="24" color="#e6a23c"><Tickets /></el-icon>
            <span style="margin-left: 10px; font-weight: bold">最近接收的日志</span>
            <el-tag type="info" size="small" style="margin-left: 10px">
              {{ filteredLogs.length }} 条
            </el-tag>
          </div>
          <div class="header-right">
            <el-input
              v-model="searchKeyword"
              placeholder="搜索日志内容..."
              style="width: 250px; margin-right: 10px"
              clearable
              @input="handleSearch"
            >
              <template #prefix>
                <el-icon><Search /></el-icon>
              </template>
            </el-input>
            <el-select 
              v-model="filterLevel" 
              placeholder="日志级别" 
              style="width: 120px; margin-right: 10px"
              clearable
              @change="handleFilter"
            >
              <el-option label="全部级别" value="" />
              <el-option label="DEBUG" value="DEBUG" />
              <el-option label="INFO" value="INFO" />
              <el-option label="WARN" value="WARN" />
              <el-option label="ERROR" value="ERROR" />
            </el-select>
            <el-select 
              v-model="filterSystem" 
              placeholder="系统类型" 
              style="width: 130px"
              clearable
              @change="handleFilter"
            >
              <el-option label="全部系统" value="" />
              <el-option label="NETWORK" value="NETWORK" />
              <el-option 
                v-for="system in uniqueSystems" 
                :key="system" 
                :label="system" 
                :value="system" 
              />
            </el-select>
          </div>
        </div>
      </template>
      <div class="log-stream">
        <div v-if="filteredLogs.length === 0" class="empty-logs">
          <el-empty description="暂无日志数据" />
        </div>
        <div v-else class="log-list">
          <div 
            v-for="(log, index) in filteredLogs" 
            :key="log.id || index" 
            class="log-item"
            :class="{ 'expanded': expandedLogId === log.id }"
            @click="toggleLogExpand(log.id)"
          >
            <div class="log-main">
              <span class="log-index">{{ index + 1 }}</span>
              <span class="log-time">{{ formatTime(log.timestamp || log.createTime) }}</span>
              <el-tag :type="getLevelType(log.logLevel)" size="small" class="log-level">
                {{ log.logLevel || 'INFO' }}
              </el-tag>
              <el-tag v-if="log.systemType" type="info" size="small" class="log-system">
                {{ log.systemType }}
              </el-tag>
              <span class="log-content">{{ truncateContent(log.content) }}</span>
              <el-icon class="expand-icon" v-if="isLongContent(log.content)">
                <ArrowDown v-if="expandedLogId !== log.id" />
                <ArrowUp v-else />
              </el-icon>
            </div>
            <div v-if="expandedLogId === log.id && isLongContent(log.content)" class="log-detail">
              <el-divider style="margin: 10px 0" />
              <div class="full-content">
                <span class="content-label">完整内容：</span>
                <pre>{{ log.content }}</pre>
              </div>
              <div class="log-meta" v-if="isJsonContent(log.content)">
                <span class="content-label">JSON格式：</span>
                <pre class="json-preview">{{ formatJson(log.content) }}</pre>
              </div>
            </div>
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { 
  Refresh, Connection, DataAnalysis, Document, 
  CircleCheck, Tickets, Download, Search, 
  ArrowDown, ArrowUp, CircleClose, TrendCharts, PieChart
} from '@element-plus/icons-vue'
import { getSourceMonitor } from '@/api/logSource'
import { queryLogs, exportLogs } from '@/api/log'

// 网络日志的采集源ID（后端NettyLogHandler中定义为4）
const NETWORK_SOURCE_ID = 4

const loading = ref(false)
const refreshing = ref(false)
const serverRunning = ref(true)

// 监控数据 - 使用 reactive 而不是 ref
const monitorData = reactive({
  successCount: 0,
  failCount: 0,
  lastCollectTime: null,
  lastHeartbeat: null,
  errorMsg: null
})

const recentLogs = ref([])

// 筛选和搜索相关
const searchKeyword = ref('')
const filterLevel = ref('')
const filterSystem = ref('')
const expandedLogId = ref(null)

let timer = null

// 确保 recentLogs 总是数组（防御性编程）
const safeRecentLogs = computed(() => {
  return Array.isArray(recentLogs.value) ? recentLogs.value : []
})

// 计算总接收数
const totalReceived = computed(() => {
  return (monitorData.successCount || 0) + (monitorData.failCount || 0)
})

// 计算成功率
const successRate = computed(() => {
  const total = totalReceived.value
  if (total === 0) return 0
  return Math.round((monitorData.successCount || 0) / total * 100)
})

// 获取唯一的系统类型列表
const uniqueSystems = computed(() => {
  const systems = new Set()
  safeRecentLogs.value.forEach(log => {
    if (log.systemType && log.systemType !== 'NETWORK') {
      systems.add(log.systemType)
    }
  })
  return Array.from(systems)
})

// 日志级别统计
const levelStats = computed(() => {
  const stats = {}
  const logs = safeRecentLogs.value
  const total = logs.length
  
  if (total === 0) return []
  
  logs.forEach(log => {
    const level = log.logLevel || 'INFO'
    stats[level] = (stats[level] || 0) + 1
  })
  
  return Object.entries(stats)
    .map(([level, count]) => ({
      level,
      count,
      percentage: Math.round((count / total) * 100)
    }))
    .sort((a, b) => b.count - a.count)
})

// 筛选后的日志列表
const filteredLogs = computed(() => {
  let logs = [...safeRecentLogs.value]
  
  // 按级别筛选
  if (filterLevel.value) {
    logs = logs.filter(log => log.logLevel === filterLevel.value)
  }
  
  // 按系统类型筛选
  if (filterSystem.value) {
    logs = logs.filter(log => log.systemType === filterSystem.value)
  }
  
  // 按关键词搜索
  if (searchKeyword.value) {
    const keyword = searchKeyword.value.toLowerCase()
    logs = logs.filter(log => 
      log.content?.toLowerCase().includes(keyword)
    )
  }
  
  return logs
})

// 获取进度条颜色
const getProgressColor = (percentage) => {
  if (percentage >= 90) return '#67c23a'
  if (percentage >= 70) return '#e6a23c'
  return '#f56c6c'
}

// 获取成功率颜色
const getSuccessRateColor = (percentage) => {
  if (percentage >= 90) return '#67c23a'
  if (percentage >= 70) return '#e6a23c'
  return '#f56c6c'
}

// 获取日志级别对应的标签类型
const getLevelType = (level) => {
  const typeMap = {
    'DEBUG': '',
    'INFO': 'info',
    'WARN': 'warning',
    'ERROR': 'danger'
  }
  return typeMap[level] || 'info'
}

// 获取日志级别对应的颜色
const getLevelColor = (level) => {
  const colorMap = {
    'DEBUG': '#909399',
    'INFO': '#409eff',
    'WARN': '#e6a23c',
    'ERROR': '#f56c6c'
  }
  return colorMap[level] || '#409eff'
}

// 格式化时间
const formatTime = (timeStr) => {
  if (!timeStr) return '-'
  try {
    const date = new Date(timeStr)
    return date.toLocaleString('zh-CN', { 
      year: 'numeric',
      month: '2-digit', 
      day: '2-digit',
      hour: '2-digit', 
      minute: '2-digit', 
      second: '2-digit' 
    })
  } catch (e) {
    return timeStr
  }
}

// 截断内容显示
const truncateContent = (content) => {
  if (!content) return '-'
  const maxLength = 150
  if (content.length <= maxLength) return content
  return content.substring(0, maxLength) + '...'
}

// 判断是否为长内容
const isLongContent = (content) => {
  return content && content.length > 150
}

// 判断是否为JSON内容
const isJsonContent = (content) => {
  if (!content) return false
  try {
    JSON.parse(content)
    return true
  } catch (e) {
    return false
  }
}

// 格式化JSON
const formatJson = (content) => {
  try {
    const obj = JSON.parse(content)
    return JSON.stringify(obj, null, 2)
  } catch (e) {
    return content
  }
}

// 切换日志展开状态
const toggleLogExpand = (logId) => {
  expandedLogId.value = expandedLogId.value === logId ? null : logId
}

// 处理搜索
const handleSearch = () => {
  // 搜索会自动通过 computed 属性触发
}

// 处理筛选
const handleFilter = () => {
  // 筛选会自动通过 computed 属性触发
  expandedLogId.value = null // 重置展开状态
}

// 导出日志
const handleExport = async () => {
  try {
    const params = {
      sourceId: NETWORK_SOURCE_ID,
      pageNum: 1,
      pageSize: 1000,
      sortField: 'timestamp',
      sortOrder: 'desc'
    }
    
    // 应用当前筛选条件
    if (filterLevel.value) {
      params.logLevel = filterLevel.value
    }
    if (filterSystem.value) {
      params.systemType = filterSystem.value
    }
    if (searchKeyword.value) {
      params.keyword = searchKeyword.value
    }
    
    const blob = await exportLogs(params)
    
    // 创建下载链接
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `network_logs_${new Date().getTime()}.xlsx`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    
    ElMessage.success('日志导出成功')
  } catch (error) {
    console.error('导出日志失败:', error)
    ElMessage.error('导出日志失败，请重试')
  }
}

// 加载监控数据
const loadMonitorData = async () => {
  try {
    const res = await getSourceMonitor(NETWORK_SOURCE_ID)
    if (res.code === 200 && res.data) {
      // 使用 Object.assign 更新 reactive 对象
      Object.assign(monitorData, res.data)
      // 根据心跳时间判断服务是否运行
      if (res.data.lastHeartbeat) {
        const heartbeatTime = new Date(res.data.lastHeartbeat).getTime()
        const now = Date.now()
        // 如果心跳时间超过5分钟，认为服务可能停止
        serverRunning.value = (now - heartbeatTime) < 5 * 60 * 1000
      }
    } else {
      // 如果没有数据，重置为默认值
      Object.assign(monitorData, {
        successCount: 0,
        failCount: 0,
        lastCollectTime: null,
        lastHeartbeat: null,
        errorMsg: null
      })
    }
  } catch (error) {
    console.error('加载监控数据失败:', error)
    // 出错时重置为默认值
    Object.assign(monitorData, {
      successCount: 0,
      failCount: 0,
      lastCollectTime: null,
      lastHeartbeat: null,
      errorMsg: null
    })
  }
}

// 加载最近的日志
const loadRecentLogs = async () => {
  try {
    const res = await queryLogs({
      sourceId: NETWORK_SOURCE_ID,
      pageNum: 1,
      pageSize: 50, // 增加到50条以便更好地统计
      sortField: 'timestamp',
      sortOrder: 'desc'
    })
    if (res.code === 200 && res.data) {
      // 确保总是数组类型
      recentLogs.value = res.data.records || res.data.list || []
    } else {
      // 如果请求失败，确保是空数组
      recentLogs.value = []
    }
  } catch (error) {
    console.error('加载最近日志失败:', error)
    // 出错时也要设置为空数组
    recentLogs.value = []
  }
}

// 刷新所有数据
const loadData = async () => {
  loading.value = true
  try {
    await Promise.all([
      loadMonitorData(),
      loadRecentLogs()
    ])
  } finally {
    loading.value = false
  }
}

// 手动刷新
const refreshData = async () => {
  refreshing.value = true
  try {
    await loadData()
    ElMessage.success('数据已刷新')
  } finally {
    refreshing.value = false
  }
}

onMounted(() => {
  // 首次加载
  loadData()
  
  // 每5秒自动刷新
  timer = setInterval(() => {
    loadData()
  }, 5000)
})

onUnmounted(() => {
  if (timer) {
    clearInterval(timer)
  }
})
</script>

<style scoped lang="scss">
.network-log {
  padding: 20px;
  
  .page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
    
    .page-title {
      font-size: 24px;
      font-weight: 600;
      color: #303133;
      margin: 0;
    }
    
    .header-actions {
      display: flex;
      gap: 10px;
    }
  }
  
  // 统计卡片样式
  .stats-row {
    margin-bottom: 20px;
    
    .stat-card {
      transition: all 0.3s ease;
      cursor: pointer;
      
      &:hover {
        transform: translateY(-4px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      }
      
      &.success {
        border-left: 3px solid #67c23a;
      }
      
      &.danger {
        border-left: 3px solid #f56c6c;
      }
      
      :deep(.el-statistic__head) {
        font-size: 13px;
        color: #909399;
        margin-bottom: 8px;
      }
      
      :deep(.el-statistic__content) {
        font-size: 24px;
        font-weight: 600;
      }
    }
  }
  
  .card-header {
    display: flex;
    align-items: center;
    
    .header-left {
      display: flex;
      align-items: center;
      flex: 1;
    }
    
    .header-right {
      display: flex;
      align-items: center;
      gap: 8px;
      flex-wrap: wrap;
      
      @media (max-width: 768px) {
        width: 100%;
        margin-top: 10px;
      }
    }
  }
  
  .service-card,
  .stats-card {
    height: 100%;
    
    @media (max-width: 768px) {
      margin-bottom: 16px;
    }
  }
  
  .service-status {
    text-align: center;
    padding: 20px 0;
  }
  
  // 日志级别统计
  .level-stats {
    padding: 10px 0;
    
    .level-item {
      margin-bottom: 16px;
      
      &:last-child {
        margin-bottom: 0;
      }
      
      .level-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        
        .level-count {
          font-size: 14px;
          color: #606266;
          font-weight: 500;
        }
      }
    }
  }
  
  // 日志卡片
  .log-card {
    :deep(.el-card__header) {
      padding: 16px 20px;
    }
  }
  
  .log-stream {
    max-height: 600px;
    overflow-y: auto;
    background: linear-gradient(to bottom, #1a1d2e, #16192a);
    border-radius: 8px;
    padding: 16px;
    font-family: 'Courier New', 'Consolas', 'Monaco', monospace;
    
    // 自定义滚动条
    &::-webkit-scrollbar {
      width: 8px;
    }
    
    &::-webkit-scrollbar-track {
      background: rgba(255, 255, 255, 0.05);
      border-radius: 4px;
    }
    
    &::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, 0.2);
      border-radius: 4px;
      
      &:hover {
        background: rgba(255, 255, 255, 0.3);
      }
    }
    
    .empty-logs {
      padding: 60px 0;
      text-align: center;
      
      :deep(.el-empty) {
        padding: 0;
      }
    }
    
    .log-list {
      .log-item {
        background-color: rgba(255, 255, 255, 0.02);
        border-radius: 6px;
        margin-bottom: 8px;
        padding: 12px;
        border: 1px solid rgba(255, 255, 255, 0.05);
        transition: all 0.3s ease;
        cursor: pointer;
        
        &:hover {
          background-color: rgba(255, 255, 255, 0.05);
          border-color: rgba(64, 158, 255, 0.3);
          transform: translateX(2px);
        }
        
        &.expanded {
          background-color: rgba(64, 158, 255, 0.08);
          border-color: rgba(64, 158, 255, 0.5);
        }
        
        .log-main {
          display: flex;
          align-items: center;
          gap: 10px;
          flex-wrap: wrap;
          
          .log-index {
            color: #666;
            min-width: 30px;
            font-weight: bold;
            font-size: 12px;
          }
          
          .log-time {
            color: #68a3d8;
            min-width: 170px;
            font-size: 12px;
            font-weight: 500;
          }
          
          .log-level,
          .log-system {
            flex-shrink: 0;
          }
          
          .log-content {
            flex: 1;
            color: #d4d4d4;
            font-size: 13px;
            line-height: 1.6;
            word-break: break-word;
            min-width: 200px;
          }
          
          .expand-icon {
            color: #909399;
            font-size: 14px;
            transition: transform 0.3s ease;
            flex-shrink: 0;
          }
        }
        
        .log-detail {
          margin-top: 12px;
          
          .content-label {
            color: #909399;
            font-size: 12px;
            font-weight: 600;
            display: block;
            margin-bottom: 6px;
          }
          
          .full-content,
          .log-meta {
            margin-bottom: 12px;
            
            pre {
              background-color: rgba(0, 0, 0, 0.3);
              border: 1px solid rgba(255, 255, 255, 0.1);
              border-radius: 4px;
              padding: 12px;
              margin: 0;
              color: #e0e0e0;
              font-size: 12px;
              line-height: 1.6;
              overflow-x: auto;
              white-space: pre-wrap;
              word-wrap: break-word;
              
              &::-webkit-scrollbar {
                height: 6px;
              }
              
              &::-webkit-scrollbar-track {
                background: rgba(255, 255, 255, 0.05);
              }
              
              &::-webkit-scrollbar-thumb {
                background: rgba(255, 255, 255, 0.2);
                border-radius: 3px;
              }
            }
            
            &:last-child {
              margin-bottom: 0;
            }
          }
          
          .json-preview {
            background: linear-gradient(135deg, #1e3a5f 0%, #2a1e3a 100%);
            border-color: rgba(64, 158, 255, 0.3);
          }
        }
      }
    }
  }
  
  // 响应式设计
  @media (max-width: 768px) {
    padding: 12px;
    
    .page-header {
      flex-direction: column;
      align-items: flex-start;
      gap: 12px;
      
      .page-title {
        font-size: 20px;
      }
      
      .header-actions {
        width: 100%;
        
        .el-button {
          flex: 1;
        }
      }
    }
    
    .card-header {
      flex-direction: column;
      align-items: flex-start !important;
      gap: 12px;
      
      .header-left {
        width: 100%;
      }
      
      .header-right {
        width: 100%;
        
        .el-input,
        .el-select {
          width: 100% !important;
          margin: 0 0 8px 0 !important;
        }
      }
    }
    
    .log-stream {
      .log-list {
        .log-item {
          .log-main {
            .log-time {
              min-width: auto;
              font-size: 11px;
            }
            
            .log-content {
              width: 100%;
              font-size: 12px;
            }
          }
        }
      }
    }
  }
}

// 深色主题优化
:deep(.el-card) {
  transition: all 0.3s ease;
}

:deep(.el-descriptions__label) {
  font-weight: 600;
}

:deep(.el-alert) {
  p {
    margin: 4px 0;
    font-size: 13px;
  }
}
</style>

